<template>
  <el-container :style="{ height: containerHeight + 'px' }">
    <!-- 左侧部门树形菜单列表 -->
    <el-aside style=" padding: 10px 0 0 0; background: #fff; border-right: 1px solid #dfe6ec; " width="200px">
      <el-tree style="font-size: 14px" ref="leftTree" :data="deptList" node-key="id" :props="defaultProps"
               default-expand-all empty-text="暂无数据" :show-checkbox="false" :highlight-current="true"
               :expand-on-click-node="false" @node-click="handleNodeClick">
        <div class="custom-tree-node" slot-scope="{ node, data }">
          <div>
            <span v-if="data.children.length === 0">
              <i class="el-icon-document" style="color: black"></i>
            </span>

            <span v-else @click.stop="openBtn(data)">
              <i v-if="data.open" class="el-icon-circle-plus-outline" style="color: red"></i>
              <i v-else class="el-icon-remove-outline" style="color: green"></i>
            </span>

            <span style="margin-left: 2px">
              {{ node.label }}
            </span>
          </div>
        </div>
      </el-tree>
    </el-aside>

    <!-- 右侧用户数据 -->
    <!-- 表格数据 -->
    <el-main>
      <!-- 查询条件 -->
      <el-form :model="searchObject" ref="searchForm" label-width="80px" :inline="true" size="small">
        <el-form-item>
          <el-input v-model="searchObject.username" placeholder="请输入用户名" clearable/>
        </el-form-item>
        <el-form-item>
          <el-input v-model="searchObject.realName" placeholder="请输入真实姓名" clearable/>
        </el-form-item>
        <el-form-item>
          <el-input v-model="searchObject.phone" placeholder="请输入电话" clearable/>
        </el-form-item>
        <el-form-item>
          <el-button icon="el-icon-search" type="primary" @click="search(departmentId, pageNo, pageSize)">查询</el-button>
          <el-button icon="el-icon-delete" type="warning" @click="resetValue">重置</el-button>
<!--          v-if="hasPermission('sys:user:insert')"-->
          <el-button icon="el-icon-plus" type="success" @click="openAddWindow">新增</el-button>
        </el-form-item>
      </el-form>
      <!-- 用户表格数据 -->
      <el-table :height="tableHeight" :data="userList" border stripe style="width: 100%; margin-bottom: 10px">
        <el-table-column prop="username" label="用户名"></el-table-column>
        <el-table-column prop="realName" label="姓名"></el-table-column>
        <el-table-column prop="departmentName" label="所属部门"></el-table-column>
        <el-table-column prop="phone" label="电话"></el-table-column>
        <el-table-column prop="email" label="邮箱"></el-table-column>
        <el-table-column align="center" width="290" label="操作">
          <template slot-scope="scope">
            <el-button icon="el-icon-edit" type="primary" size="mini" @click="handleEdit(scope.row)">编辑</el-button>
            <el-button icon="el-icon-delete" type="danger" size="mini" @click="handleDelete(scope.row)">删除</el-button>
            <el-button icon="el-icon-setting" type="primary" size="mini" @click="assignRole(scope.row)">分配角色</el-button>
          </template>
        </el-table-column>
      </el-table>
      <!-- 分页工具栏 -->
      <el-pagination
        @current-change="handleCurrentChange"
        @size-change="handleSizeChange"
        :current-page="pageNo"
        :page-size="pageSize"
        :page-sizes="[5, 10, 20, 50, 100, total]"
        layout="total, sizes, prev, pager, next, jumper"
        :total="total"
      >
      </el-pagination>
    </el-main>

    <system-dialog :title="userDialog.title" :height="userDialog.height" :width="userDialog.width"
                   :visible="userDialog.visible" @onClose="onClose" @onConfirm="onConfirm">
      <div slot="content">
        <el-form :model="user" ref="userForm" :rules="rules" label-width="80px" :inline="true" size="small">
          <el-form-item prop="username" label="用户名">
            <el-input v-model="user.username"></el-input>
          </el-form-item>
          <el-form-item prop="password" v-if="user.id === ''" label="密码">
            <el-input type="password" v-model="user.password"></el-input>
          </el-form-item>
          <el-form-item prop="departmentName" label="所属部门">
            <el-input v-model="user.departmentName" :readonly="true" @click.native="selectDepartment"></el-input>
          </el-form-item>
          <el-form-item prop="realName" label="姓名">
            <el-input v-model="user.realName"></el-input>
          </el-form-item>
          <el-form-item prop="phone" label="电话">
            <el-input v-model="user.phone"></el-input>
          </el-form-item>
          <el-form-item label="昵称">
            <el-input v-model="user.nickName"></el-input>
          </el-form-item>
          <el-form-item label="邮箱">
            <el-input v-model="user.email"></el-input>
          </el-form-item>
          <el-form-item prop="gender" label="性别">
            <el-radio-group v-model="user.gender">
              <el-radio :label="0">男</el-radio>
              <el-radio :label="1">女</el-radio>
            </el-radio-group>
          </el-form-item>
          <br>
          <el-form-item label="头像">
            <el-upload
              class="avatar-uploader"
              :show-file-list="false"
              :on-success="handleAvatarSuccess"
              :before-upload="beforeAvatarUpload"
              :data="uploadHeader"
              action="http://localhost:7777/file/upload?module=avatar">
              <img v-if="user.avatar" :src="user.avatar">
              <i v-else class="el-icon-plus avatar-uploader-icon"></i>
            </el-upload>
          </el-form-item>
        </el-form>
      </div>
    </system-dialog>

    <system-dialog :title="parentDialog.title"
                   :width="parentDialog.width" :height="parentDialog.height" :visible="parentDialog.visible"
                   @onClose="onParentClose" @onConfirm="onParentConfirm">
      <div slot="content">
        <el-tree ref="parentTree" :data="parentList" default-expand-all node-key="id" :props="parentProps"
                 :show-checkbox="false" :highlight-current="true" :expand-on-click-node="false"
                 @node-click="parentClick">
          <div class="customer-tree-node" slot-scope="{ node, data }">

            <span v-if="data.children.length === 0">
              <i class="el-icon-document" style="color: black"></i>
            </span>

            <span v-else @click.stop="openParentBtn(data)">
              <i v-if="data.open" class="el-icon-circle-plus-outline" style="color: red"></i>
              <i v-else class="el-icon-remove-outline" style="color: green"></i>
            </span>

            <span style="margin-left: 2px">
              {{ node.label }}
            </span>

          </div>
        </el-tree>
      </div>
    </system-dialog>

    <!--    分配角色窗口-->
    <system-dialog :title="assignDialog.title" :height="assignDialog.height" :width="assignDialog.width"
                   :visible="assignDialog.visible" @onClose="onAssignClose" @onConfirm="onAssignConfirm">
      <div slot="content">
        <!-- 分配角色数据列表 -->
        <el-table ref="assignRoleTable" :data="assignRoleList" border stripe :height="assignHeight"
                  style="width: 100%; margin-bottom: 10px" @selection-change="handleSelectionChange">
          <el-table-column type="selection" width="55" align="center"></el-table-column>
          <el-table-column prop="roleCode" label="角色编码"/>
          <el-table-column prop="roleName" label="角色名称"/>
          <el-table-column prop="remark" label="角色备注"/>
        </el-table>
        <el-pagination
          @current-change="assignCurrentChange"
          @size-change="assignSizeChange"
          :current-page.sync="roleVo.pageNo"
          :page-sizes="[5, 10, 20, 50, 100]"
          :page-size="roleVo.pageSize"
          layout="total, sizes, prev, pager, next, jumper"
          :total="roleVo.total"
        >
        </el-pagination>
      </div>
    </system-dialog>

  </el-container>
</template>

<script>

    import systemDialog from '@/components/system/systemDialog.vue';
    import departmentApi from '@/api/department';
    import userApi from '@/api/user';
    import {getToken} from '@/utils/auth';

    export default {
        name: "userList",
        components: {
            systemDialog
        },
        data() {
            //自定义电话号码校验规则
            let validatePhone = (rule, value, callback) => {
                if (!value) {
                    callback(new Error("请输入手机号码"));
                    //使用正则表达式进行验证手机号码
                } else if (!/^1[3456789]\d{9}$/.test(value)) {
                    callback(new Error("手机号格式不正确"));
                } else {
                    callback();
                }
            };
            return {
                //上传需要携带的数据
                uploadHeader: {"token": getToken()},
                //容器高度
                containerHeight: 0,
                //左侧部门树形菜单列表
                deptList: [],
                defaultProps: {
                    children: 'children',
                    label: 'departmentName'
                },
                searchObject: {
                    username: "",
                    realName: "",
                    phone: "",
                    departmentId: "",
                    pageNo: 1,
                    pageSize: 10
                },
                //用户列表
                userList: [],
                //表格高度
                tableHeight: 0,
                //当前页码
                pageNo: 1,
                //每页显示数量
                pageSize: 10,
                //总数量
                total: 0,
                //部门编号
                departmentId: "",

                //添加和修改用户窗口属性
                userDialog: {
                    title: '',
                    height: 410,
                    width: 610,
                    visible: false
                },
                //用户对象
                user: {
                    id: '',
                    departmentId: '',
                    departmentName: '',
                    email: '',
                    realName: '',
                    phone: '',
                    nickName: '',
                    password: '',
                    username: '',
                    gender: '',
                    avatar: ''
                },
                rules: {
                    departmentName: [{required: true, trigger: 'change', message: '请选择所属部门'}],
                    realName: [{required: true, trigger: 'blur', message: '请填写姓名'}],
                    phone: [{required: true, trigger: 'blur', validator: validatePhone}],
                    username: [{required: true, trigger: 'blur', message: '请填写用户名'}],
                    password: [{required: true, trigger: 'blur', message: '请填写登录密码'}],
                    gender: [{required: true, trigger: 'change', message: '请选择性别'}]
                },

                parentDialog: {
                    title: '请选择所属部门',
                    width: 300,
                    height: 450,
                    visible: false
                },
                parentProps: {
                    children: 'children',
                    label: 'departmentName'
                },
                parentList: [],
                assignDialog: {title: "", visible: false, width: 800, height: 410},
                roleVo: {pageNo: 1, pageSize: 10, userId: "", total: 0},
                //角色列表
                assignRoleList: [],
                //分配角色表格高度
                assignHeight: 0,
                //被选中的角色id
                selectedIds: [],
                //被分配角色的用户ID
                selectedUserId: ""
            }
        },
        mounted() {
            this.$nextTick(() => {
                //内容高度
                this.containerHeight = window.innerHeight - 85;
                //表格高度
                this.tableHeight = window.innerHeight - 220;
                //角色表格高度
                this.assignHeight = window.innerHeight - 350;
            })
        },
        created() {
            this.getDeptList();
            this.search(this.departmentId);
        },
        methods: {
            async assignRole(row) {
                //防止回显出现问题
                this.selectedIds = [];
                this.selectedUserId = "";
                //被分配用户的id
                this.selectedUserId = row.id;
                //显示窗口
                this.assignDialog.visible = true;
                //设置标题
                this.assignDialog.title = `【${row.realName}】用户角色分配`;
                //查询当前登录用户的所有角色信息
                await this.getAssignRoleList();
                //获取当前被分配用户的ID
                let params = {
                    userId: row.id
                };
                //发送根据用户ID查询角色列表的请求
                let res = await userApi.getRoleIdByUserId(params);
                //如果存在数据
                if (res.success && res.data) {
                    //将查询到的角色ID列表交给选中角色数组
                    this.selectedIds = res.data;
                    //循环遍历
                    this.selectedIds.forEach((key) => {
                        this.assignRoleList.forEach((item) => {
                            if (item.id === key) {
                                this.$refs.assignRoleTable.toggleRowSelection(item, true);
                            }
                        });
                    });
                }
            },
            async getAssignRoleList(pageNo = 1, pageSize = 10) {
                //给用户ID赋值
                this.roleVo.userId = this.$store.getters.userId;
                this.roleVo.pageNo = pageNo;
                this.roleVo.pageSize = pageSize;
                //发送查询请求
                let res = await userApi.getAssignRoleList(this.roleVo);
                //判断是否成功
                if (res.success) {
                    //角色列表赋值
                    this.assignRoleList = res.data.records;
                    //角色总数量赋值
                    this.roleVo.total = res.data.total;
                }
            },
            onAssignClose() {
                this.assignDialog.visible = false;
            },
            //分配角色确认事件
            async onAssignConfirm() {
                this.assignDialog.visible = false;
                //判断用户是否有选中角色
                if (this.selectedIds.length === 0) {
                    this.$message.warning("请选择要分配的角色");
                    return;
                }
                let params = {
                    userId: this.selectedUserId,
                    roleIds: this.selectedIds
                };
                let res = await userApi.assignRoleSave(params);
                if (res.success) {
                    this.$message.success(res.message);
                    this.assignDialog.visible = false;
                } else {
                    this.$message.error(res.message);
                }
            },
            assignSizeChange(size) {
                this.roleVo.pageSize = size;
                this.getAssignRoleList(this.roleVo.pageNo, size);
            },
            assignCurrentChange(page) {
                this.roleVo.pageNo = page;
                this.getAssignRoleList(page, this.roleVo.pageSize);
            },
            handleSelectionChange(rows) {
                let roleIds = []; //循环遍历选中的角色ID
                for (let i = 0; i < rows.length; i++) {
                    //将当前选中的角色ID放到数组中
                    roleIds.push(rows[i].id);
                }
                //将选中的角色ID交给成员变量
                this.selectedIds = roleIds;
                // this.selectedIds = rows.map(item => item.id);//等同于上述代码
            },
            //上传前的校验
            beforeAvatarUpload(file) {
                const isJPG = file.type === 'image/jpeg'
                const isLt2M = file.size / 1024 / 1024 < 2
                if (!isJPG) {
                    this.$message.error('上传头像图片只能是 JPG 格式!')
                }
                if (!isLt2M) {
                    this.$message.error('上传头像图片大小不能超过 2MB!')
                }
                return isJPG && isLt2M
            },
            //上传成功回调
            handleAvatarSuccess(res) {
                this.user.avatar = res.data;
                // 强制重新渲染
                this.$forceUpdate();
            },
            /**
             * 查询部门列表
             * @param data
             */
            async getDeptList() {
                //发送查询请求
                let res = await departmentApi.getDepartmentList(null);
                //判断是否成功
                if (res.success) {
                    this.deptList = res.data;
                    //树加载完成后，默认点击第一个节点
                    this.$nextTick(() => {
                        const firstNode = document.querySelector(".el-tree-node");
                        firstNode.click();
                    })
                }
            },
            //查询用户列表
            async search(departmentId, pageNo = 1, pageSize = 10) {
                this.searchObject.pageNo = pageNo;
                this.searchObject.pageSize = pageSize;
                this.searchObject.departmentId = departmentId;
                //发送查询请求
                let res = await userApi.getUserList(this.searchObject);
                if (res.success) {
                    this.userList = res.data.records;
                    this.total = res.data.total;
                }
            },
            handleSizeChange(size) {
                //将每页显示的数量交给成员变量
                this.pageSize = size;
                this.search(this.departmentId, this.pageNo, size);
            },
            handleCurrentChange(page) {
                //将当前页交给成员变量
                this.pageNo = page;
                this.search(this.departmentId, page, this.pageSize);
            },
            resetValue() {
                this.searchObject = {};
                this.search(this.departmentId);
            },
            /**
             * 左侧树节点点击事件
             * @param data
             */
            handleNodeClick(data) {
                //给部门编号赋值
                this.departmentId = data.id;
                //查询数据
                this.search(this.departmentId);
            },
            /**
             * 加减号图标点击事件
             * @param data
             */
            openBtn(data) {
                //修改折叠展开状态
                data.open = !data.open;
                this.$refs.leftTree.store.nodesMap[data.id].expanded = !data.open;
            },
            openAddWindow() {
                this.$resetForm('userForm', this.user);
                this.userDialog.title = '新增用户';
                this.userDialog.visible = true;
            },
            handleEdit(row) {
                this.userDialog.title = '编辑用户';
                this.userDialog.visible = true;
                this.$objCopy(row, this.user);
            },
            async handleDelete(row) {
                let confirm = await this.$commonConfirm("确定要删除该数据吗？");
                let params = {id: row.id};
                let res = await userApi.deleteUser(params);
                if (res.success) {
                    this.$message.success(res.message);
                    this.search(this.departmentId, this.pageNo, this.pageSize);
                } else {
                    this.$message.error(res.message)
                }
            },
            onClose() {
                this.userDialog.visible = false;
            },
            onConfirm() {
                this.$refs.userForm.validate(async (valid) => {
                    if (valid) {
                        let res = null;
                        if (this.user.id === '') {
                            res = await userApi.addUser(this.user);
                        } else {
                            res = await userApi.updateUser(this.user);
                        }
                        if (res.success) {
                            this.$message.success(res.message);
                            this.search(this.departmentId, this.pageNo, this.pageSize);
                            this.userDialog.visible = false;
                        } else {
                            this.$message.error(res.message);
                        }
                    }
                })
            },
            async selectDepartment() {
                let res = await departmentApi.getDepartmentList(null);
                if (res.success) {
                    this.parentList = res.data;
                }
                this.parentDialog.visible = true;
            },
            onParentClose() {
                this.parentDialog.visible = false;
            },
            onParentConfirm() {
                this.parentDialog.visible = false;
            },
            parentClick(data) {
                this.user.departmentId = data.id;
                this.user.departmentName = data.departmentName;
            },
            openParentBtn(data) {
                data.open = !data.open;
                this.$refs.parentTree.store.nodesMap[data.id].expanded = !data.open;
            }
        }
    }
</script>

<style lang="scss">
  .avatar-uploader .el-upload {
    border: 1px dashed #d9d9d9 !important;
    border-radius: 6px;
    cursor: pointer;
    position: relative;
    overflow: hidden;
  }

  .avatar-uploader .el-upload:hover {
    border-color: #409EFF;
  }

  .avatar-uploader .avatar-uploader-icon {
    font-size: 28px;
    color: #8c939d;
    width: 178px;
    height: 178px;
    line-height: 178px;
    text-align: center;
  }

  .avatar-uploader img {
    width: 178px;
    height: 178px;
    display: block;
  }
</style>
